package com.luiz.gymmoves.persistence;

import java.lang.reflect.Field;

import com.luiz.gymmoves.persistence.annotations.Atributte;
import com.luiz.gymmoves.persistence.annotations.ComplexType;
import com.luiz.gymmoves.persistence.annotations.PrimaryKey;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteConstraintException;
import android.database.sqlite.SQLiteDatabase;

public class GenericDAO {

	public long save(Context context, Object object) {
		if (object == null)
			return -1;
		if (new DBManager().isMappedClass(object.getClass().getSimpleName())) {
			SQLiteDatabase db = null;
			ContentValues ct = new ContentValues();
			try {
				Field[] fields = object.getClass().getDeclaredFields();
				for (Field f : fields) {
					f.setAccessible(true);
					if (f.getAnnotation(PrimaryKey.class) != null) {
						if ((f.get(object) != null) && (f.getLong(object) > 0)) {
							putToField(object, f, ct);
						} else {
							ct.putNull(f.getName());
						}
					} else if (f.getAnnotation(Atributte.class) != null) {
						putToField(object, f, ct);
					} else if (f.getAnnotation(ComplexType.class) != null) {
						ct.put(f.getType().getSimpleName() + "_id",
								(long) save(context, f.get(object)));
					}
				}
				db = new DBOpenHelper(context).getWritableDatabase();
				long key = db.insertOrThrow(object.getClass().getSimpleName(),
						null, ct);
				db.close();
				return key;
			} catch (SQLiteConstraintException ex) {
				db.close();
				Field[] innerFields = object.getClass().getDeclaredFields();
				for (Field f : innerFields) {
					f.setAccessible(true);
					if (f.getAnnotation(PrimaryKey.class) != null) {
						try {
							return f.getInt(object);
						} catch (Exception e) {
							e.printStackTrace();
							return -1;
						}
					}
				}
				return -1;
			} catch (Exception ex) {
				ex.printStackTrace();
				db.close();
				return -1;
			}
		} else
			return -1;

	}

	private void putToField(Object object, Field f, ContentValues ct)
			throws IllegalArgumentException, IllegalAccessException {
		if (f.getType().getSimpleName().equals("String")) {
			ct.put(f.getName(), (String) f.get(object));
		} else if (f.getType().getSimpleName().equals("int")
				|| (f.getType() == Integer.class)) {
			ct.put(f.getName(), (Integer) f.get(object));
		} else if (f.getType().getSimpleName().equals("long")
				|| (f.getType() == Long.class)) {
			ct.put(f.getName(), (Long) f.get(object));
		}

	}

	public int remove(Context context, Object object) {
		if (object == null) {
			return -1;
		}
		if (new DBManager().isMappedClass(object.getClass().getSimpleName())) {
			try {
				Field[] fields = object.getClass().getDeclaredFields();
				for (Field f : fields) {
					f.setAccessible(true);
					if (f.getAnnotation(PrimaryKey.class) != null) {
						if (f.getInt(object) > 0) {
							SQLiteDatabase db = new DBOpenHelper(context)
									.getWritableDatabase();
							db.delete(object.getClass().getSimpleName(),
									f.getName() + "=" + f.getInt(object), null);
							db.close();
						}
					}
				}
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}

		return -1;
	}

	public Object searchId(Context context, Object object) {
		if (object == null)
			return null;
		if (new DBManager().isMappedClass(object.getClass().getSimpleName())) {
			Cursor cursor = null;
			SQLiteDatabase database = null;
			try {

				Field[] fields = object.getClass().getDeclaredFields();
				for (Field f : fields) {
					f.setAccessible(true);
					if (f.getAnnotation(PrimaryKey.class) != null) {
						database = new DBOpenHelper(context)
								.getReadableDatabase();
						cursor = database.rawQuery("SELECT * FROM "
								+ object.getClass().getSimpleName() + " WHERE "
								+ f.getName() + "=" + f.getInt(object), null);
					}
				}
				cursor.moveToFirst();
				for (Field f : fields) {
					f.setAccessible(true);
					getFieldValue(f, object, cursor);
				}
				cursor.close();
				database.close();
				return object;
			} catch (Exception ex) {
				ex.printStackTrace();
			} finally {
				cursor.close();
				database.close();
			}
		}

		return null;
	}

	private Object getFieldValue(Field field, Object object, Cursor cursor)
			throws IllegalArgumentException, IllegalAccessException {
		String fieldName = field.getName();
		if (field.getAnnotation(ComplexType.class) != null)
			fieldName = fieldName.concat("_id");
		if (field.getType() == String.class) {
			int fdp = cursor.getColumnIndex(fieldName);
			field.set(object, cursor.getString(fdp));
		} else if (field.getType().getSimpleName().equals("int")
				|| field.getType() == Integer.class) {
			field.set(object, cursor.getInt(cursor.getColumnIndex(fieldName)));
		} else if (field.getType().getSimpleName().equals("long")
				|| field.getType() == Long.class) {
			field.set(object, cursor.getLong(cursor.getColumnIndex(fieldName)));
		}

		return object;
	}

}
